﻿namespace NJQuery {
	using System;
	using System.ComponentModel;

	/// <summary>
	/// Server control used to define the properties of a <see href="http://docs.jquery.com/UI/Effects/Shake">jQuery UI Shank effect</see>, which shakes the element multiple times, vertically or horizontally.
	/// </summary>
	public class ShakeEffect : EffectBase {


		#region Constants: Property defaults

		private const ShakeDirection defaultDirection = ShakeDirection.Left;
		private const int defaultDistance = 20;
		private const int defaultTimes = 3;

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="ShakeEffect"/> class.
		/// </summary>
		public ShakeEffect() : base("shake") { }

		#endregion


		#region Properties: Initialization options

		/// <summary>
		/// The direction of the effect.
		/// This property maps directly to the "direction" option when the jQuery UI effect is initialized.
		/// </summary>
		/// <exception cref="ArgumentException">Value not defined.</exception>
		[DefaultValue(defaultDirection), Category("Behavior")]
		public virtual ShakeDirection Direction {
			get { return ViewState["Direction"] as ShakeDirection? ?? defaultDirection; }
			set {
				if(!Enum.IsDefined(typeof(ShakeDirection), value)) throw new ArgumentException("Value not defined.", "value");
				ViewState["Direction"] = value;
			}
		}

		/// <summary>
		/// Distance to shake (in pixels).
		/// This property maps directly to the "distance" option when the jQuery UI effect is initialized.
		/// </summary>
		[DefaultValue(defaultDistance), Category("Behavior")]
		public virtual int Distance {
			get { return ViewState["Distance"] as int? ?? defaultDistance; }
			set { ViewState["Distance"] = value; }
		}

		/// <summary>
		/// Times to shake.
		/// This property maps directly to the "times" option when the jQuery UI effect is initialized.
		/// </summary>
		[DefaultValue(defaultTimes), Category("Behavior")]
		public virtual int Times {
			get { return ViewState["Times"] as int? ?? defaultTimes; }
			set { ViewState["Times"] = value; }
		}

		#endregion


		#region Methods: Rendering hooks

		/// <summary>
		/// Allows a jQuery server control to reference scripts and stylesheets necessary to render their client markup and widgets.
		/// </summary>
		/// <param name="manager">The <see cref="Manager"/> used to handle style and script referencing in addition to unified generation of load and ready scripts.</param>
		protected override void Register(Manager manager) {
			base.Register(manager);

			manager.RegisterClientScript(ClientScript.UIShakeEffect);
		}

		/// <summary>
		/// Returns a <see cref="PropertyCollection"/> containing option values specific to the effect.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <returns>A <see cref="PropertyCollection"/> containing the effect's option values.</returns>
		protected override PropertyCollection CreateOptionProperties() {
			PropertyCollection properties = base.CreateOptionProperties();

			ShakeDirection direction = Direction;
			if(direction != defaultDirection) properties.AddEnumValue("direction", direction);

			int distance = Distance;
			if(distance != defaultDistance) properties.AddValue("distance", distance);

			int times = Times;
			if(times != defaultTimes) properties.AddValue("times", times);

			return properties;
		}

		#endregion


	}

}